package com.kamkor.interviewer.client.presenter;

import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasText;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.UIObject.DebugIdImpl;
import com.kamkor.interviewer.client.InterviewServiceAsync;
import com.kamkor.interviewer.client.Interviewer;
import com.kamkor.interviewer.client.LoadingIndicator;
import com.kamkor.interviewer.client.event.MergeInterviewEvent;
import com.kamkor.interviewer.client.security.Authentication;
import com.kamkor.interviewer.client.view.DeleteQuestionAnswerButton;
import com.kamkor.interviewer.client.view.TextChangedHandler;
import com.kamkor.interviewer.shared.QuestionAnswerDetails;

/**
 * 
 * @author kamkor
 *
 */
public class EditInterviewPresenter extends SecuredPresenter{			
	private final InterviewServiceAsync rpcService;
	private final Display display;
	private final HandlerManager eventBus;	
	
	/** 
	 * ClickHandler for delete buttons associated with QuestionAnswers. 
	 * Each QuestionAnswer panel in view has one delete button.
	 * 
	 * @author kamkor
	 */
	public class DeleteQuestionAnswerClickHandler implements ClickHandler {		
		@Override
		public void onClick(ClickEvent event) {		
			final DeleteQuestionAnswerButton deleteButton = (DeleteQuestionAnswerButton) event.getSource();
			final Long id = deleteButton.getId();
			rpcService.deleteQuestionAnswer(id, new AsyncCallback<Void>() {
				@Override
				public void onFailure(Throwable caught) {
										
				}
				@Override
				public void onSuccess(Void result) {
					display.deleteQuestionAnswerPanel(id, deleteButton);
				}				
			});
		}		
	}
	
	public interface Display extends DisplaysSaveInfo {
		FlexTable getQuestionAnswerTable();	
		HasClickHandlers getAddQuestion();
		HasClickHandlers getSaveAll();
		HasClickHandlers getMerge();		
		HasText getAddQuestionArea();		
		void setQuestionAnswerTextChangeHandler(ChangeHandler handler);
		void setDeleteQuestionAnswerButtonsHandler(ClickHandler handler);
		void setData(List<QuestionAnswerDetails> list);		
		List<QuestionAnswerDetails> getData(Long interviewId);
		void addToData(QuestionAnswerDetails questionAnswer);
		void deleteQuestionAnswerPanel(Long id, PushButton deleteButton);
		Widget asWidget();	
	}
	
	public EditInterviewPresenter(InterviewServiceAsync rpcService, Display display, HandlerManager eventBus, 
			Long interviewId, Long adminKey, Authentication authentication) {
		super(authentication, interviewId, adminKey);
		this.rpcService = rpcService;
		this.display = display;
		this.eventBus = eventBus;
	}
	
	public void bind() {
		display.getAddQuestion().addClickHandler(new ClickHandler() {			
			public void onClick(ClickEvent event) {
				doAdd();			
			}			
		});
		
		display.getSaveAll().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				doSaveAll();			
			}		
		});
		
		display.getMerge().addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				// maybe doSaveAll()? Or ask user first			
				eventBus.fireEvent(new MergeInterviewEvent(getInterviewId(), getKey()));								
			}			
		});
		
		display.setDeleteQuestionAnswerButtonsHandler(new DeleteQuestionAnswerClickHandler());		
		display.setQuestionAnswerTextChangeHandler(new TextChangedHandler(display, Interviewer.constants.questionOrQuestionsAreNotSaved()));
		display.getIsSavedInfo().setText(Interviewer.constants.allSaved());		
	}
	
	/** 
	 * Load QuestionAnswer from database and add them to flexTable 
	 */
	private void fetchQuestionAnswer(Long interviewId) {
		LoadingIndicator.loadingStarted(Interviewer.constants.loading());
		rpcService.getQuestionAnswer(interviewId, new AsyncCallback<List<QuestionAnswerDetails>>() {			
			public void onFailure(Throwable caught) {
				LoadingIndicator.loadingFinished();	
			}		
			public void onSuccess(List<QuestionAnswerDetails> result) {
				// bad solution, have to iterate result twice. In presenter and in view.
				for (QuestionAnswerDetails qa : result) {
					qa.setQuestionShort(createQuestionShortcut(qa.getQuestion(), 0, 70, "..."));
				}
				display.setData(result);	
				LoadingIndicator.loadingFinished();	
			}			
		});				
	}
	
	/**
	 * Adds new question to the interview
	 */
	private void doAdd() {		
		String question = display.getAddQuestionArea().getText();
		LoadingIndicator.loadingStarted(Interviewer.constants.loading());
		rpcService.createQuestionAnswer(getInterviewId(), question, "", new AsyncCallback<QuestionAnswerDetails>() {
			public void onFailure(Throwable caught) {	
				LoadingIndicator.loadingFinished();	
			}		
			public void onSuccess(QuestionAnswerDetails result) {	
				result.setQuestionShort(createQuestionShortcut(result.getQuestion(), 0, 70, "..."));
				display.addToData(result);	
				LoadingIndicator.loadingFinished();	
			}				
		});
	}
	
	private void doSaveAll() {		
		List<QuestionAnswerDetails> list = display.getData(getInterviewId());
		LoadingIndicator.loadingStarted(Interviewer.constants.loading());
		rpcService.updateQuestionAnswer(list, new AsyncCallback<Void>() {			
			public void onFailure(Throwable caught) {
				LoadingIndicator.loadingFinished();	
			}			
			public void onSuccess(Void result) {	
				LoadingIndicator.loadingFinished();	
				Label isSavedInfo = display.getIsSavedInfo();
				isSavedInfo.setText(Interviewer.constants.allSaved());
				isSavedInfo.setStyleName("textSaved");	
			}
		});
	}
	
	/**
	 * If append is not empty or not null and endIndex < question.length(), 
	 * it will be added to the shortened question. 
	 * 
	 * if endIndex > question.length(), then endIndex = question.length()
	 * 
	 * before adding append, if questionShortcut is trimmed.  
	 * 
	 * @param question
	 * @param beginIndex substring beginIndex
	 * @param endIndex substring endIndex
	 * @param append what to append to the end of question
	 * @return shortened question
	 */
	public String createQuestionShortcut(final String question, final int beginIndex, int endIndex, final String append) {		
		final int length = question.length();
		if (endIndex > length) {
			endIndex = length;
		} 
		
		String questionShortcut = question.substring(beginIndex, endIndex).trim();		
		if (append != null && append != "" && endIndex < length) {
			return questionShortcut + append;
		} else {
			return questionShortcut;
		}		
	}

	@Override
	public void authenticationFailed() {
				
	}

	@Override
	protected void goAuthenticated(HasWidgets container) {
		bind();
		container.clear();	
		container.add(display.asWidget());		
		fetchQuestionAnswer(getInterviewId());	
	}	
}
